#pragma once

#include <cmath>
#include <initializer_list>
#include <vector>

using Real = double;

template <int Dim>
class Vector
{
public:
    Vector()
    {
        for (int i = 0; i < Dim; i++)
            value[i] = 0;
    }
    Vector(std::initializer_list<Real> l) : Vector()
    {
        int i = 0;
        for (auto it = l.begin(); it != l.end(); ++it, ++i)
            value[i] = *it;
    }
    Vector(const Vector &v)
    {
        for (int i = 0; i < Dim; i++)
            value[i] = v[i];
    }
    void operator=(const Vector &v)
    {
        for (int i = 0; i < Dim; i++)
            value[i] = v[i];
    }

    Real operator[](int i) const
    {
        return value[i];
    }
    Real &operator[](int i)
    {
        return value[i];
    }

    int size() const { return Dim; }

public:
    Real value[Dim];
};

template <int Row, int Col>
class Matrix
{
public:
    Matrix()
    {
        for (int i = 0; i < Row; i++)
        {
            for (int j = 0; j < Col; j++)
            {
                value[i * Col + j] = 0;
            }
        }
    }
    Matrix(std::initializer_list<Real> l)
    {
        auto it = l.begin();
        for (int i = 0; i < Row; i++)
        {
            for (int j = 0; j < Col; j++)
            {
                value[i * Col + j] = *it;
                ++it;
            }
        }
    }
    Matrix(const Matrix &m)
    {
        for (int i = 0; i < Row; i++)
        {
            for (int j = 0; j < Col; j++)
            {
                value[i * Col + j] = m.coord(i, j);
            }
        }
    }
    void operator=(const Matrix &m)
    {
        for (int i = 0; i < Row; i++)
        {
            for (int j = 0; j < Col; j++)
            {
                value[i * Col + j] = m.coord(i, j);
            }
        }
    }

    Real coord(int i, int j) const
    {
        return value[i * Col + j];
    }
    Real &coord(int i, int j)
    {
        return value[i * Col + j];
    }

    int row() const { return Row; }
    int col() const { return Col; }

    // 矩阵乘向量
    Vector<Row> operator*(const Vector<Col> &v)
    {
        Vector<Row> v1;
        for (int i = 0; i < Row; i++)
        {
            for (int j = 0; j < Col; j++)
            {
                v1[i] += value[i * Col + j] * v[j];
            }
        }
        return v1;
    }
    // 矩阵乘矩阵
    template <int Col2>
    Matrix<Row, Col2> operator*(const Matrix<Col, Col2> &m)
    {
        Matrix m1;
        for (int i = 0; i < Row; i++)
        {
            for (int j = 0; j < Col2; j++)
            {
                for (int k = 0; k < Col; k++)
                {
                    m1.coord(i, j) += coord(i, k) * m.coord(k, j);
                }
            }
        }
        return m1;
    }

public:
    Real value[Row * Col];
};

// 定义一般容器
using vec3d = Vector<3>;
using mat3d = Matrix<3, 3>;